﻿using System;
using System.Collections.Generic;
using System.Text;

public class CRC
{
   public  ushort CRCVal;
      
    public CRC()
    {
        CRCVal = 0xFFFF;
    }
    
    public void CRCStart(ushort Seed)
    {
        CRCVal = Seed;    
    }

    public void Step(byte Data)
    {
        CRCVal = (ushort)((byte)(CRCVal >> 8) | (CRCVal << 8));
        CRCVal ^= Data;
        CRCVal ^= (ushort)((byte)(CRCVal & 0xff) >> 4);
        CRCVal ^= (ushort)((CRCVal << 8) << 4);
        CRCVal ^= (ushort)(((CRCVal & 0xff) << 4) << 1);
    }

    public void Step(sbyte Data)
    {
        CRCVal = (ushort)((byte)(CRCVal >> 8) | (CRCVal << 8));
        CRCVal ^= (byte)Data;
        CRCVal ^= (ushort)((byte)(CRCVal & 0xff) >> 4);
        CRCVal ^= (ushort)((CRCVal << 8) << 4);
        CRCVal ^= (ushort)(((CRCVal & 0xff) << 4) << 1);
    }

    public void Step(short Data)
    {
        CRCVal = (ushort)((byte)(CRCVal >> 8) | (CRCVal << 8));
        CRCVal ^= (byte)(Data&0xFF);
        CRCVal ^= (ushort)((byte)(CRCVal & 0xff) >> 4);
        CRCVal ^= (ushort)((CRCVal << 8) << 4);
        CRCVal ^= (ushort)(((CRCVal & 0xff) << 4) << 1);

        CRCVal = (ushort)((byte)(CRCVal >> 8) | (CRCVal << 8));
        CRCVal ^= (byte)((Data>>8) & 0xFF);
        CRCVal ^= (ushort)((byte)(CRCVal & 0xff) >> 4);
        CRCVal ^= (ushort)((CRCVal << 8) << 4);
        CRCVal ^= (ushort)(((CRCVal & 0xff) << 4) << 1);
    }

    public void Step(ushort Data)
    {
        CRCVal = (ushort)((byte)(CRCVal >> 8) | (CRCVal << 8));
        CRCVal ^= (byte)(Data & 0xFF);
        CRCVal ^= (ushort)((byte)(CRCVal & 0xff) >> 4);
        CRCVal ^= (ushort)((CRCVal << 8) << 4);
        CRCVal ^= (ushort)(((CRCVal & 0xff) << 4) << 1);

        CRCVal = (ushort)((byte)(CRCVal >> 8) | (CRCVal << 8));
        CRCVal ^= (byte)((Data >> 8) & 0xFF);
        CRCVal ^= (ushort)((byte)(CRCVal & 0xff) >> 4);
        CRCVal ^= (ushort)((CRCVal << 8) << 4);
        CRCVal ^= (ushort)(((CRCVal & 0xff) << 4) << 1);
    }

    public void Step(byte [] Data)
    {
        for(int i=0;i<Data.Length;i++)
        {
            CRCVal = (ushort)((byte)(CRCVal >> 8) | (CRCVal << 8));
            CRCVal ^= Data[i];
            CRCVal ^= (ushort)((byte)(CRCVal & 0xff) >> 4);
            CRCVal ^= (ushort)((CRCVal << 8) << 4);
            CRCVal ^= (ushort)(((CRCVal & 0xff) << 4) << 1);
        }
    }

    static public ushort Calculate(byte[] Data, ushort Length)
    {
        ushort i, ecrc;
        ecrc = 0xffff;
        for (i = 0; i < Length; i++)
        {
            ecrc = (ushort)((Byte)(ecrc >> 8) | (ecrc << 8));
            ecrc ^= Data[i];
            ecrc ^= (ushort)((Byte)(ecrc & 0xff) >> 4);
            ecrc ^= (ushort)((ecrc << 8) << 4);
            ecrc ^= (ushort)(((ecrc & 0xff) << 4) << 1);
        }
        return ecrc;
    }

}